navigator.getUserMedia = navigator.getUserMedia ||
navigator.webkitGetUserMedia || window.navigator.mozGetUserMedia;
window.URL = window.URL || window.webkitURL;
if (navigator.mozGetUserMedia) {
    RTCPeerConnection = mozRTCPeerConnection;
    RTCSessionDescription = mozRTCSessionDescription;
    RTCIceCandidate =mozRTCIceCandidate;
}
else if (navigator.webkitGetUserMedia) {
    RTCPeerConnection = webkitRTCPeerConnection;
}
else {
    alert("Your browser do not support WebRTC communication");
}

var dataChannel;
var peerConnection;
var currentoffer = null;
var sdp = "";
var firstPeerTextBox = document.getElementById('from-first-peer');
var firstPeerOutput = document.getElementById('messages-sent-by-second-peer');

var isChrome = !!navigator.webkitGetUserMedia;
var iceServers = [];
iceServers.push({ url: 'stun:stun.miwifi.com:3478' });
pc_config = { iceServers: iceServers};

//////////////////////////////////////////////////////////////////////////////////
var websocket ;
var WEBSOCKET_ADDR = 'ws://122.152.200.206:7600/ws';

function getPeerId() {
    var len = 9;
    var timestamp = parseInt((new Date()).valueOf()/1000);
    var  x="0123456789qwertyuioplkjhgfdsazxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM";
    var  tmp="";
    for(var  i=0;i<  len;i++)  {
        tmp  +=  x.charAt(Math.ceil(Math.random()*100000000)%x.length);
    }
    return  timestamp+'-'+tmp;
}

var g_peer_id = getPeerId();
var g_offer_id;
var g_remote_mac;
var g_path_name;

//信令处理。
function pear_signal_handshake(path_name)
{
    var self = this;
    var websocket = new WebSocket(WEBSOCKET_ADDR);
    self.websocket = websocket;
    g_path_name = path_name;

    websocket.onopen = function() {
        var hash = "df3545633423543";
        createPeerConnect();
        websocket.push(JSON.stringify({
            "action": "get",
            "peer_id": g_peer_id,
            "host": "www.pear.hk",
            "uri": path_name,
            "md5": hash
        }));
    };

    websocket.push = websocket.send;
    websocket.send = function(data) {
        if (websocket.readyState != 1) {
            console.warn('websocket connection is not opened yet.');
            return setTimeout(function() {
                websocket.send(data);
            }, 1000);
        }
        websocket.push(data);
    };

    websocket.onmessage = function(e) {
        var message = JSON.parse(e.data);
        //字段错误 message -> message.candidates
        if (message.nodes) {
            var nodes = message.nodes;
            for (var i = 0; i < nodes.length; ++i) {
                var offer = nodes[i];
                if (!offer.errorcode) {
                    g_offer_id = offer.offer_id;
                    g_remote_mac  = offer.peer_id;
                    if (g_remote_mac) {
                        if (offer.sdp.type === 'offer') {
                            receiveOffer(offer.sdp);
                            break;
                        }
                    }
                    else {
                        debug('datachannel 重复');
                    }
                } else {
                    debug('dc error message:'+JSON.stringify(message))
                }
            }
        }
        else if (message.action === 'answer') {
            if (!message.errorcode) {
                if (message.sdp.type === 'answer') {
                    receiveAnswer(message.sdp);
                }
            }
        }
        else if (message.action === 'candidate') {
            if (!message.errorcode) {
                ReceiveIceCandidate(message.candidate);
            }
        }
    };
}

//ice处理。
function createPeerConnect() {
    try {
        peerConnection = new RTCPeerConnection(pc_config);
        console.log("Peerconnection Connection established !");
    }
    catch (e) {
        console.log("pc established error："+e.message);
    }

    peerConnection.onopen = function() {
        console.log("PeerConnection established");
    };

    peerConnection.onicecandidate = function (event) {
        if (event.candidate == null) {
            if (sdp == "") {
                console.log("sdp error");
                return;
            }
            return;
        } else {

            var src_candidate = JSON.stringify({
                "peer_id":g_peer_id,
                "to_peer_id":g_remote_mac,
                "offer_id":g_offer_id,
                "action":"candidate",
                "candidates": event.candidate
            });
            console.log("src_candidate: "+ src_candidate);
            socketSend(src_candidate);
        }
        console.log("iceGatheringState: "+ peerConnection.iceGatheringState);
    };

    peerConnection.oniceconnectionstatechange = function (evt) {
        console.log("iceGatheringState: "+ peerConnection.iceConnectionState);
        console.log("signalingstate:"+ peerConnection.signalingState);
        console.log("pc Connection state: "+peerConnection.connectionState);
        if (peerConnection.signalingState == "stable")
        {
            createDatachannel();
        }
    };

    peerConnection.ondatachannel = function (evt) {
        dataChannel = evt.channel;
        console.log(dataChannel.label+"dc state: "+ dataChannel.readyState);
        dataChannelEvents(dataChannel);
    };

    //通过信令告诉，终端本次candidata addr结束。
    peerConnection.onicegatheringstatechange = function() {
        if (peerConnection.iceGatheringState === 'complete') {
            var src_completed = JSON.stringify({
                "peer_id":g_peer_id,
                "to_peer_id":g_remote_mac,
                 "offer_id":g_offer_id,
                 "action":"candidate",
                 "candidates":{
                    "candidate":"completed"
                }
            });
            socketSend(src_completed);
        }
    };
}

function createDatachannel() {
    try {
        dataChannel = peerConnection.createDataChannel('dataChannel', {reliable: true});
        console.log("Channel [ " + dataChannel.label + " ] created!");
        console.log(dataChannel.label+" Datachannel state: "+ dataChannel.readyState);
    }
    catch (dce) {
        console.log("dc established error: " + dce.message);
    }
    dataChannelEvents(dataChannel);
}


function buf2hex(buffer) { // buffer is an ArrayBuffer
    // create a byte array (Uint8Array) that we can use to read the array buffer
    const byteArray = new Uint8Array(buffer);
    
    // for each element, we want to get its two-digit hexadecimal representation
    const hexParts = [];
    for(let i = 0; i < byteArray.length; i++) {
      // convert value to hexadecimal
      const hex = byteArray[i].toString(16);
      
      // pad with zeros to length 2
      const paddedHex = ('00' + hex).slice(-2);
      
      // push to array
      hexParts.push(paddedHex);
    }
    
    // join all the hex values of the elements into a single string
    return hexParts.join('');
  }

var count = 0;
//DCchannel处理
function dataChannelEvents(channel) {
    channel.onopen = function () {
        console.log("Datachannel opened, current stateis :\n" + dataChannel.readyState);
        console.log(channel);
        if (!count) {
            var src_data = JSON.stringify({
                "host":"www.pear.hk",
                "uri":g_path_name,
                "action":"get",
                "response_type":"binary",
                "start" :0,
                "end":5242879
            });
            channel.send(src_data);
            count = 1;
        }
    };

    //数据接受处理，请查看datachannel_file_transfer_protocol.md关于数据的格式。
    channel.onmessage = function (event) {
        console.log("recv" + event.data.byteLength);
        console.log(buf2hex(event.data));
    };

    channel.onerror = function (err) {
        console.log("Datachannel Error: "+err);
    }

    channel.onclose = function () {
        console.log("DataChannel is closed");
    }
}

function sendOffer() {
    peerConnection.createOffer(function (desc) {
        currentoffer = desc;
        console.log("Create an offer : \n"+JSON.stringify(desc));
        peerConnection.setLocalDescription(desc);
        console.log("Offer Set as Local Desc");
        socketSend(desc);
        sdp = desc.sdp;
        console.log("Send offer:\n"+JSON.stringify(sdp));
    },function(error) {
            console.log(error);
    });
}

function receiveOffer(evt) {
    peerConnection.setRemoteDescription(new RTCSessionDescription(evt));
    console.log("Received Offer, and set as Remote Desc:\n"+ evt.sdp);
    peerConnection.createAnswer(function(desc) {
        peerConnection.setLocalDescription(desc);
        currentoffer = desc;
        var str_Answer = JSON.stringify({
            "peer_id":g_peer_id,
            "to_peer_id":g_remote_mac,
            "offer_id":g_offer_id,
            "action":"answer",
            "sdps":desc
        });

        console.log("Create Answer, and set as Local Desc:\n"+ JSON.stringify(str_Answer));
        console.log("Create Answer, and set as Local Desc:\n"+ str_Answer);
        socketSend(str_Answer);
    },function (err) {
        console.log(err);
    });
}

function receiveAnswer(answer) {
    console.log("Received remote Answer: \n"+JSON.stringify(answer));
    peerConnection.setRemoteDescription(new RTCSessionDescription(answer));
    console.log("already set remote desc, current ice gather state: "+ peerConnection.iceGatheringState);
}

function ReceiveIceCandidate(evt) {
    if (evt) {
        console.log("Received and add candidate:\n"+JSON.stringify(evt));
        peerConnection.addIceCandidate(new RTCIceCandidate(evt));
    } else {
        return;
    }
}

function socketSend(msg) {
    websocket.send(msg);
}


function onError(e) { 
    if (e.message) alert("onError: " + e.message); 
    else alert(e); 
}

//html相关
var path_name = '';
window.onload = function () {
    console.log("onload");
    var path_name_input = document.getElementById('path_name');
    var download_button = document.getElementById('download');
    path_name_input.oninput = function(event){
        console.log("change", event.target.value);
        path_name = event.target.value;
        if(path_name){
            download_button.disabled = false;
        }else{
            download_button.disabled = true;
        }
    }
};

